﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FernUniHagen.CompilerExtension.DataStructures;
using FernUniHagen.CompilerExtension.Functions;
using Roslyn.Compilers.Common;
using Roslyn.Compilers.CSharp;
using Roslyn.Services;

namespace FernUniHagen.CompilerExtension
{
    /// <summary>
    /// This class should check if the code is valid
    /// </summary>
    public static class PreProcessor
    {
        //FOR FIELDS:
        //01.06.2013 Not necessary as C# Compiler will find a type error - Todo: Check if attribute has more than one argument for any, none for option and bare (should be done by compiler)
        //01.06.2013 Finished - Todo: Check if there are not more than one multiplicity attributes assigned
        //TODO: Check if walker would not be a better approach for preprocessor
        //TODO: Check logging frameworks
        //Todo: Check the arguments of the multiplicity attributes
        //Todo: Check that type of the field is simple (e.g.: should not be a collection etc)

   

        public static List<string> CheckProject(ISolution solution)
        {
            List<string> results = new List<string>();
            foreach (var project in solution.Projects)
            {
                foreach (IDocument doc in project.Documents)
                {
                    ISemanticModel semanticModel = doc.GetSemanticModel();
                    SemanticModel model = (SemanticModel)doc.GetSemanticModel();
                    SyntaxTree tree = (SyntaxTree)doc.GetSyntaxTree();
                    results.AddRange(CheckMultiplicityAttributes(solution, model, tree));
                }
            }
            return results;
        }

        /// <summary>
        /// Checks if there is only one multiplicity item on a field
        /// In case of "Any" Attribute it also checks wheter the parameters are correct 
        /// </summary>
        /// <param name="semanticModel">the semantic model</param>
        /// <param name="tree">the syntaxtree</param>
        /// <returns>empty list if no errors found, otherwise the errors are in the list</returns>
        private static List<string> CheckMultiplicityAttributes(ISolution solution, SemanticModel semanticModel,SyntaxTree tree)
        {
            List<string> results = new List<string>();
            CompilationUnitSyntax syntax = tree.GetRoot();
            IEnumerable<FieldDeclarationSyntax> fieldDeclarations = syntax.DescendantNodes().OfType<FieldDeclarationSyntax>();
            List<AttributeSyntax> multiplicityAttributes;
            foreach (FieldDeclarationSyntax node in fieldDeclarations)
            {
                //multiplicityAttributes = Utilities.GetMultiplicityAttribute(node.AttributeLists,node.;
                
                ////Check if there is only one multiplicity attribute annotated
                //if (multiplicityAttributes.Count > 1)
                //    results.Add(ReportCompilerError(node, "There were too many multiplicity attributes on this item:"));
                ////if there is only one, check if there 

                //else if (multiplicityAttributes.Count == 1)
                //{
                //   // TODO: Attribute Converter has been removed...We need to do the validation again
                //   // AttributeConverter attrConverter = AttributeConverter.GetInstance(solution, semanticModel, multiplicityAttributes.First());
                //   // string parametersCorrect = attrConverter.Validate(node);
                //   // if (!string.IsNullOrEmpty(parametersCorrect)) results.Add(ReportCompilerError(node, parametersCorrect));
                //}
            }
            return results;
        }

        private static string ReportCompilerError(CommonSyntaxNode node, string message)
        {
            return string.Format("{0} - {1} - {2}: {3}\n", node.GetLocation().SourceTree.FilePath, node.GetLocation().SourceSpan.Start,   
                message, node.ToFullString());

        }

        public static List<string> CheckSyntaxNodes( List<DataStructures.SyntaxNodeInfo> annotatedSyntaxNodes)
        {
            
            List<string> errors = new List<string>();
            //foreach (SyntaxNodeInfo nodeInfo in annotatedSyntaxNodes)
            //{
                
            //    AttributeType attrType = AttributeType.None;
            //    GenericNameSyntax name = null;
            //    errors = Utilities.GetMultiplicityAttribute(nodeInfo.NodeToReplace, out attrType, out name);
            //    //TODO:Check if attribute has valid container by getting the ISemenaticModel 
            //    foreach (var error in errors)
            //    {
            //        ReportCompilerError(nodeInfo.NodeToReplace, error);
            //    }
            //}
            return errors;
        }
    }
}
